﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MessageWorkflow.Handler;

namespace MessageWorkflow.Test
{
    [TestClass]
    public class WorkflowChannelTest
    {
        [TestMethod]
        public void Channel_Dispatch_Raises_Exception()
        {
            WorkflowChannel channel = new WorkflowChannel();
            channel.Subscribe<string>(x => { throw new InvalidOperationException("test"); });

            try
            {
                channel.Dispatch("test");

                Assert.Fail("Should have fallen in catchblock");
            }
            catch (InvalidOperationException)
            {

            }
        }   

        [TestMethod]
        public void Channel_Dispatch_Waits_Before_Return()
        {
            // see: http://stackoverflow.com/questions/5465565/system-action-not-known-in-unittest-untill-explicitly-defined
            Action useless = null;
            if (useless != null) {  }

            WorkflowChannel channel = new WorkflowChannel();
            bool isHandeled = false;

            channel.Subscribe(WorkflowHandlerFactory.FromLambdaAsync<int>((data, callback, onError) =>
            {
                // Go on another thread and sleep for a small ammount of time to simulate a async request
                System.Threading.ThreadPool.QueueUserWorkItem(state =>
                {
                    System.Threading.Thread.Sleep(100);
                    
                    isHandeled = true;

                    callback();
                });
            }));


            channel.Dispatch(1);

            Assert.IsTrue(isHandeled);
        }

        [TestMethod]
        public void Channel_Raises_Events_When_Subscribing_Handlers()
        {
            WorkflowChannel channel = new WorkflowChannel();

            int counter = 0;
            channel.HandlerSubscribed += new EventHandler<HandlerSubscribedEventArgs>((sender, e) =>
            {
                counter++;
            });

            IWorkflowHandler emptyHandler1 = WorkflowHandlerFactory.FromLambda<int>(x => {});
            IWorkflowHandler emptyHandler2 = WorkflowHandlerFactory.FromLambda<int>(x => {});
            IWorkflowHandler emptyHandler3 = WorkflowHandlerFactory.FromLambda<int>(x => {});

            channel.Subscribe(new WorkflowHandlerConfiguration(emptyHandler1)
            {
                Successors = new[]
                {
                    new WorkflowHandlerConfiguration(emptyHandler2)
                }
            });

            channel.Subscribe(emptyHandler3);

            Assert.AreEqual(counter, 3);
        }

        [TestMethod]
        public void Channel_Raises_Events_When_Unsubscribing_Handlers()
        {
            WorkflowChannel channel = new WorkflowChannel();

            int counter = 0;
            channel.HandlerUnsubscribed += new EventHandler<HandlerUnsubscribedEventArgs>((sender, e) => 
            {
                counter++;
            });

            IWorkflowHandler emptyHandler1 = WorkflowHandlerFactory.FromLambda<int>(x => { });
            IWorkflowHandler emptyHandler2 = WorkflowHandlerFactory.FromLambda<int>(x => { });
            IWorkflowHandler emptyHandler3 = WorkflowHandlerFactory.FromLambda<int>(x => { });

            channel.Subscribe(new WorkflowHandlerConfiguration(emptyHandler1)
            {
                Successors = new[]
                {
                    new WorkflowHandlerConfiguration(emptyHandler2)
                }
            });

            channel.Subscribe(emptyHandler3);

            channel.UnsubscribeHandler(emptyHandler1);
            channel.UnsubscribeHandler(emptyHandler2);
            channel.UnsubscribeHandler(emptyHandler3);
            
            Assert.AreEqual(counter, 3);
        }

        [TestMethod]
        public void Override_Default_Channel_Works()
        {
            WorkflowChannel newChannel = new WorkflowChannel();
            WorkflowChannel.OverrideDefault(newChannel);

            Assert.AreEqual(WorkflowChannel.Default, newChannel);
        }

        [TestMethod]
        public void Dynamic_Workflow_Handlers_Can_Be_Matched()
        {
            var action = new Func<AsyncCallback, int, IAsyncResult>((x1, x2) => { return null; });

            IWorkflowHandler handler1 = new DynamicWorkflowHandler<int>(false, action);
            IWorkflowHandler handler2 = new DynamicWorkflowHandler<int>(false, action);

            Assert.AreEqual(handler1, handler2);
        }
    }
}
